package com.djmw.mouse.web.member;

import java.util.Enumeration;
import java.util.List;

import javax.servlet.ServletRequest;
import javax.validation.Validator;

import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.json.JSONException;
import org.json.JSONStringer;
import org.json.JSONWriter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.djmw.mouse.entity.Cv;
import com.djmw.mouse.entity.CvEducation;
import com.djmw.mouse.entity.CvLang;
import com.djmw.mouse.entity.CvWorkingExperience;
import com.djmw.mouse.entity.MemberUser;
import com.djmw.mouse.service.CvLangService;
import com.djmw.mouse.service.CvService;
import com.djmw.mouse.service.account.MemberAccountService;
import com.djmw.mouse.service.account.ShiroDbRealm.ShiroUser;
import com.djmw.mouse.service.constants.Constants;

/**
 * 个人Profile（即原来的CV）管理的Controller, 使用Restful风格的Urls:
 * 
 * View page : GET /member/profile/view/{id} <br>
 * Edit page : GET /member/profile/edit <br>
 * Update action : POST /member/profile/update <br>
 * 
 * @author michael
 */

@Controller
@RequestMapping(value = "/member/profile")
public class ProfileCvController {

    @Autowired
    private CvService cvService;
    @Autowired
    private CvLangService cvLangService;
    @Autowired
    private MemberAccountService memberAccountService;
    @Autowired
    private Validator validator;

    @RequestMapping(value = "view")
    public String viewMine(RedirectAttributes redirectAttributes, ServletRequest request) {
        return "redirect:/member/profile/view/" + getCurrentUser().getId();
    }

    @RequestMapping(value = "view/{id}")
    public String view(@PathVariable("id") Long memberUserId, Model model, ServletRequest request) {
        MemberUser memberUser = memberAccountService.getUser(memberUserId);
        if (memberUser == null) {
            // Invalid User.
            return "error/404";
        }
        List<Cv> cvs = cvService.getMemberCvList(memberUserId, false);
        Cv cv;
        if (cvs == null || cvs.size() == 0) {
            // Create empty CV if necessary.
            cv = new Cv("个人简介");
            cv.setMemberUser(memberUser);
            CvLang cvLang = new CvLang(cv, CvLang.LANG_CHINESE);
            cv.setCurCvLang(cvLang);
        } else {
            cv = cvs.get(CvLang.LANG_CHINESE);
        }
        addFormConstants(model);
        model.addAttribute("cv", cv);
        model.addAttribute("memberUser", memberUser);
        return "member/profile";
    }

    @RequestMapping(value = "edit", method = RequestMethod.GET)
    public String updateForm(Model model) {
        MemberUser memberUser = memberAccountService.getUser(getCurrentUser().getId());
        if (memberUser == null) {
            // Invalid User.
            return "error/404";
        }
        List<Cv> cvs = cvService.getMemberCvList(memberUser.getId(), false);
        Cv cv;
        if (cvs == null || cvs.size() == 0) {
            // Create empty CV if necessary.
            cv = new Cv("个人简介");
            cv.setMemberUser(memberUser);
            CvLang cvLang = new CvLang(cv, CvLang.LANG_CHINESE);
            cv.setCurCvLang(cvLang);
        } else {
            cv = cvs.get(CvLang.LANG_CHINESE);
        }
        addFormConstants(model);
        model.addAttribute("cv", cv);
        model.addAttribute("memberUser", memberUser);
        return "member/profile-edit";
    }

    @RequestMapping(value = "update", method = RequestMethod.GET)
    @ResponseBody
    public String update(@ModelAttribute("preloadCV") ProfileUpdateInfo info,
            @RequestParam(value = "_baseInfoUpdated", defaultValue = "true") Boolean _baseInfoUpdated,
            ServletRequest request) {
        Enumeration<?> e1 = request.getParameterNames();
        Logger.getLogger(ProfileCvController.class).info("------Start--------");
        while (e1.hasMoreElements()) {
            String name = (String) e1.nextElement();
            String value = request.getParameter(name);
            Logger.getLogger(ProfileCvController.class).info(name + ":" + value);
        }
        Logger.getLogger(ProfileCvController.class).info("------End--------");
        CvLang cvLang = info.getCv().getCurCvLang();
        CvEducation education = info.getEdu();
        if (education != null) {
            if (education.getId() == null) {
                // Add new
                education.setCvLang(cvLang);
                cvLang.getCvEducation().add(education);
            } else {
                // Update
                cvLang.updateCvEducation(education);
            }
        }
        CvWorkingExperience work = info.getWork();
        if (work != null) {
            if (work.getId() == null) {
                // Add new
                work.setCvLang(cvLang);
                cvLang.getCvWorkingExperience().add(work);
            } else {
                // Update current
                cvLang.updateCvWorkingExperience(work);
            }
        }
        info.getCv().getCurCvLang().normalize();
        cvService.saveCv(info.getCv());
        // cvLangService.saveCvLang(cv.getCurCvLang());
        if (Boolean.TRUE.equals(_baseInfoUpdated)) {
            MemberUser user = getCurrentUser();
            MemberUser user2 = memberAccountService.getUser(user.getId());
            user2.updateBaseInfo(info.getCv().getMemberUser());
            memberAccountService.updateUser(user2);
        }
        // TODO: Calculate memberUser's profileCompletion.
        try {
            JSONStringer json = new JSONStringer();
            JSONWriter writer = json.object().key("msg").value("ok");
            if (education != null) {
                writer.key("cvEduId").value(education.getId());
            }
            if (work != null) {
                writer.key("cvWorkId").value(work.getId());
            }
            writer.endObject();
            return writer.toString();
        } catch (JSONException e) {
            e.printStackTrace();
            return "{\"msg\":\"ok\"}";
        }
    }

    /**
     * 使用@ModelAttribute, 实现Struts2
     * Preparable二次部分绑定的效果,先根据form的id从数据库查出CV对象,再把Form提交的内容绑定到该对象上。
     * 因为仅update()方法的form中有id属性，因此本方法在该方法中执行.
     */
    @ModelAttribute("preloadCV")
    public ProfileUpdateInfo getProfileUpdateInfo(@RequestParam(value = "cv.id", required = false) Long id,
            @RequestParam(value = "cv.curLang", required = false) Integer curLang) {
        if (id == null && curLang == null) {
            return null;
        }
        Cv cv = id == null ? new Cv() : cvService.getCv(id);
        if (curLang == null) {
            curLang = CvLang.LANG_CHINESE;
        }
        cv.setCurLang(curLang);
        if (cv.getCurCvLang() == null) {
            cv.setCurCvLang(new CvLang(cv, curLang));
        }
        ProfileUpdateInfo info = new ProfileUpdateInfo();
        info.setCv(cv);
        return info;
    }

    public MemberUser getCurrentUser() {
        ShiroUser user = (ShiroUser) SecurityUtils.getSubject().getPrincipal();
        return (MemberUser) user.getUser();
    }

    private void addFormConstants(Model model) {
        model.addAttribute("_provinces", Constants.PROVINCES);
        model.addAttribute("_cities", Constants.CITIES);
        // model.addAttribute("languages", Constants.LANGUAGES);
        // model.addAttribute("proficiencys", Constants.PROFICIENCYS);
        model.addAttribute("_educations", Constants.EDUCATIONS);
        model.addAttribute("_workingYears", Constants.WORKING_YEARS_MEMBER);
        model.addAttribute("_certTypes", Constants.CERT_TYPES);
        model.addAttribute("_salaryRanges", Constants.YEARLY_SALARY_RANGES);
        model.addAttribute("_currencies", Constants.CURRENCIES);
        model.addAttribute("_situations", Constants.SITUATIONS);
        model.addAttribute("_countries", Constants.COUNTRIES);
        model.addAttribute("_marriageStatus", Constants.MARRIAGE_STATUS);
        model.addAttribute("_politicalStatus", Constants.POLITICAL_STATUS);
        model.addAttribute("_degrees", Constants.EDUCATIONS);
        model.addAttribute("_companySizes", Constants.COMPANY_SIZES);
        model.addAttribute("_companyTypes", Constants.COMPANY_TYPES);
        // model.addAttribute("majors", Constants.MAJORS);
        // model.addAttribute("jobTypes", Constants.JOB_TYPES);
        // model.addAttribute("lang", CvLang.LANG_CHINESE);
    }

    public static class ProfileUpdateInfo {
        public Cv cv;
        public CvEducation edu;
        public CvWorkingExperience work;

        public Cv getCv() {
            return cv;
        }
        public void setCv(Cv cv) {
            this.cv = cv;
        }
        public CvEducation getEdu() {
            return edu;
        }
        public void setEdu(CvEducation edu) {
            this.edu = edu;
        }
        public CvWorkingExperience getWork() {
            return work;
        }
        public void setWork(CvWorkingExperience work) {
            this.work = work;
        }
    }
}
